﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using TicketSellerService;
using System.ServiceModel.Web;
using System.ServiceModel;
using System.Net;

namespace FlightSearchServer
{
    public class FlightSearchService : IFlightSearchService
    {
        private print console = Console.WriteLine;

        public AvailableFlights flightSearch(string source, string destination, DateTime date)
        {
            AvailableFlights flights = new AvailableFlights();
            console( String.Format( "Searching for flight from {0} to {1} on {2}", source, destination, date));
            foreach (TicketsVendors vendor in VendorsDB.getInstance().getVendors())
            {
                WebChannelFactory<IFlightTicketService> cf = new WebChannelFactory<IFlightTicketService>(new Uri(vendor.location));
                IFlightTicketService proxy = cf.CreateChannel( );
                using (new OperationContextScope((IContextChannel)proxy))
                {
                    try
                    {
                        AvailableFlights res = proxy.search(source, destination, date.ToString());
                        foreach (Flight flight in res)
                            flights.Add(flight);
                    }
                    catch (Exception e)
                    {
                        if (e.InnerException is WebException)
                        {
                            HttpWebResponse response = (HttpWebResponse)((WebException)e.InnerException).Response;
                            if (response != null)
                            {
                                console("Get {0} code from vendor: {1}", response.StatusCode, vendor.name);
                                if ( response.StatusCode == HttpStatusCode.NotFound)
                                    throw new Exception( String.Format( "Flight from {0} to {1} on {2} not found", source, destination, date.ToShortDateString( )));  
                            }
                            else
                            {
                                console("Vendor {0} is down", vendor.name);
                            }
                            throw new Exception( e.Message, e.InnerException);  
                        }
                        else
                        {
                            console(e.Message);
                            throw new Exception( e.Message);  
                        }
                    }
                }
            }
            console("Found {0} fligts", flights.Count);
            return flights;
        }

        public TicketReservation flightReserve(string vendorName, string flightNum, DateTime date)
        {
            console("Reserving flight {0} on date {1}", flightNum, date);
            TicketReservation reservation = new TicketReservation( null);
            reservation.statusMessage = "FAILED.";
            TicketsVendors seller = null;
            foreach (TicketsVendors vendor in VendorsDB.getInstance().getVendors())
            {
                if (vendor.name.Equals(vendorName))
                {
                    seller = vendor;
                    break;
                }
            }
            if ( seller == null) {
                TicketReservation result = new TicketReservation( null);
                result.statusMessage = "Failed, unknow seller.";
                console("Seller with {0} name is not found", vendorName);
                throw new Exception(result.statusMessage);
            }
            WebChannelFactory<IFlightTicketService> cf = new WebChannelFactory<IFlightTicketService>( new Uri( seller.location));
            IFlightTicketService proxy = cf.CreateChannel();
            using ( new OperationContextScope( (IContextChannel)proxy)) {
                try
                {
                    reservation = proxy.reserve(flightNum, date.ToString());
                }
                catch (Exception e)
                {
                    if (e.InnerException is WebException)
                    {
                        HttpWebResponse response = (HttpWebResponse)((WebException)e.InnerException).Response;
                        if (response != null)
                        {
                            console("Get {0} code from vendor: {1}", response.StatusCode, seller.name);
                            reservation.statusMessage = response.StatusDescription;
                            throw new Exception(reservation.statusMessage);
                        }
                        else
                        {
                            console("Failed, {0} is down.", vendorName);
                            reservation.statusMessage = String.Format("Failed, {0} is down.", vendorName);
                            throw new Exception(reservation.statusMessage);
                        }
                    }
                    else
                    {
                        console(e.Message);
                        reservation.statusMessage = String.Format("Failed, {0} is down.", vendorName);
                        throw new Exception(reservation.statusMessage);
                    }
                }
            }
            return reservation;
        }

        public string reservationCancel(string vendorName, string reservationId)
        {
            string statusMessage = "Ok";
            console("Canceling reservation with id {0}", reservationId);
            TicketsVendors seller = null;
            foreach (TicketsVendors vendor in VendorsDB.getInstance().getVendors())
            {
                if (vendor.name.Equals(vendorName))
                {
                    seller = vendor;
                    break;
                }
            }
            if (seller == null)
            {
                console("Seller with {0} name is not found", vendorName);
                throw new Exception("Failed, unknow seller.");
            }
            WebChannelFactory<IFlightTicketService> cf = new WebChannelFactory<IFlightTicketService>(new Uri(seller.location));
            IFlightTicketService proxy = cf.CreateChannel();
            using (new OperationContextScope((IContextChannel)proxy))
            {
                try
                {
                   statusMessage = proxy.cancel(reservationId);
                }
                catch (Exception e)
                {
                    if (e.InnerException is WebException)
                    {
                        HttpWebResponse response = (HttpWebResponse)((WebException)e.InnerException).Response;
                        if (response != null)
                        {
                            console("Failed, cancelling reservation with id {0}. Got response {1}", reservationId, response.StatusCode);
                            statusMessage = response.StatusDescription;
                            throw new Exception(statusMessage);
                        }
                        else
                        {
                            statusMessage = String.Format("Failed, {0} is down.", vendorName);
                            console("Failed, {0} is down.", vendorName);
                            throw new Exception(statusMessage);
                        }
                    }
                    else
                    {
                        console(e.Message);
                        statusMessage = String.Format("Failed, {0} is down.", vendorName);
                        throw new Exception("Failed, unknow seller.");
                    }
                }
            }
            console("Reservation with ID: {0}  cancelled.", reservationId);
            return statusMessage;
        }
    }
}